/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-12
 * V4.0
 */
package com.jphenix.share.lang;

import com.jphenix.standard.docs.ClassInfo;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 排序处理类
 * 
 * 注意：已经增加了防止重复添加相同对象实例的控制，不存在重复元素
 * 
 * com.jphenix.share.lang.SortVector
 * 
 * 该类有两个值影响排序顺序
 * 
 * level 等级，该值优先考虑，通常人工固定设置
 * weight 权重，通常通过排序的值计算出来
 * 
 * 2019-01-02 增加了移除指定值的方法
 * 2019-01-03 增加了重置排序（准备重新获取值）
 * 
 * 
 * @author 马宝刚
 * 2009-12-2 上午09:53:34
 */
@ClassInfo({"2019-01-03 16:59","排序处理类"})
public class SortVector<E> {

	protected Node firstUpNode = null; //在排序前设置的上一个节点
	protected Node upNode = null; //上一个节点
	protected boolean asc = true; //是否由小到大
	protected List<E> list = new ArrayList<E>(); //元素序列，只用来比对内部元素是否存在
	
	/**
	 * 节点类
	 * @author 马宝刚
	 * 2009-12-2 上午09:54:43
	 */
	protected class Node {
		
		protected E value;	//元素值类实例
		protected int level; //等级
		protected double weight;	//权重
		protected Node 
				pNode		//父节点
				,cNode;		//子节点
		
		/**
		 * 构造函数
		 * @author 马宝刚
		 * @param value 元素值类实例
		 * @param level 等级
		 * @param weight 权重
		 */
		public Node(E value,int level,double weight,Node oNode) {
			super();
			this.value = value;
			this.level = level;
			this.weight = weight;
			if(oNode==null) {
				return;
			}
			if(level==oNode.level) {
				if(weight>oNode.weight) {
					oNode.upSet(this);
				}else {
					oNode.downSet(this);
				}
			}else if(level>oNode.level) {
				oNode.upSet(this);
			}else {
				oNode.downSet(this);
			}
		}
		
		/**
		 * 到下层设置节点
		 * 马宝刚
		 * 2009-12-2 上午10:33:15
		 * @param newNode 新节点
		 */
		public void downSet(Node newNode) {
			if(cNode==null) {
				cNode = newNode;
				newNode.pNode = this;
			}else {
				if(cNode.level==newNode.level) {
					if(cNode.weight>=newNode.weight) {
						cNode.downSet(newNode);
					}else {
						newNode.cNode = cNode;
						newNode.pNode = this;
						cNode.pNode = newNode;
						cNode = newNode;
					}
				}else if(cNode.level>newNode.level) {
					cNode.downSet(newNode);
				}else {
					newNode.cNode = cNode;
					newNode.pNode = this;
					cNode.pNode = newNode;
					cNode = newNode;
				}
			}
		}
		
		/**
		 * 到上层设置节点
		 * 马宝刚
		 * 2009-12-2 上午10:22:59
		 * @param newNode 新节点
		 */
		public void upSet(Node newNode) {
			if(pNode==null) {
				pNode = newNode;
				newNode.cNode = this;
			}else {
				if(pNode.level==newNode.level) {
					if(pNode.weight<newNode.weight) {
						pNode.upSet(newNode);
					}else {
						newNode.pNode = pNode;
						newNode.cNode = this;
						pNode.cNode = newNode;
						pNode = newNode;
					}
				}else if(pNode.level<newNode.level) {
					pNode.upSet(newNode);
				}else {
					newNode.pNode = pNode;
					newNode.cNode = this;
					pNode.cNode = newNode;
					pNode = newNode;
				}
			}
		}
		
		/**
		 * 获取最小权重节点
		 * 马宝刚
		 * 2009-12-2 上午10:41:20
		 * @return 最小权重节点
		 */
		public Node getBottomNode() {
			if(cNode==null) {
				return this;
			}
			return cNode.getBottomNode();
		}
		
		/**
		 * 获取最大权重的节点
		 * 马宝刚
		 * 2009-12-2 上午10:40:07
		 * @return 最大权重的节点
		 */
		public Node getTopNode() {
			if(pNode==null) {
				return this;
			}
			return pNode.getTopNode();
		}
	}
	
	/**
	 * 构造函数
	 * @author 马宝刚
	 */
	public SortVector() {
		super();
	}

	/**
	 * 添加值
	 * 马宝刚
	 * 2009-12-2 上午10:42:30
	 * @param value 值
	 * @param weight 权重
	 */
	public void add(E value,double weight) {
		if(list.contains(value)) {
			return;
		}
		list.add(value);
		upNode = new Node(value,0,weight,upNode);
		firstUpNode = upNode;
	}
	
	/**
	 * 添加值
	 * 马宝刚
	 * 2009-12-2 上午10:42:30
	 * @param value 值
	 * @param level 等级
	 * @param weight 权重
	 */
	public void add(E value,int level,double weight) {
		if(list.contains(value)) {
			return;
		}
		list.add(value);
		upNode = new Node(value,level,weight,upNode);
		firstUpNode = upNode;
	}

	/**
	 * 添加字符串值
	 * @param value 字符串值
	 * 2014年8月27日
	 * @author 马宝刚
	 */
	public void add(E value) {
		if(list.contains(value)) {
			return;
		}
		list.add(value);
		upNode = new Node(value,0,fixDouble(value),upNode);
		firstUpNode = upNode;
	}
	
	/**
	 * 添加序列
	 * @param valueList 指定序列
	 * 2015年2月19日
	 * @author 马宝刚
	 */
	public void addAll(List<E> valueList) {
	    if(valueList==null) {
	        return;
	    }
	    for(E ele:valueList) {
			if(list.contains(ele)) {
				continue;
			}
	    	list.add(ele);
	        add(ele);
	    }
	}
	
	/**
	 * 添加字符串值
	 * @param value 字符串值
	 * @param level 等级
	 * 2014年8月27日
	 * @author 马宝刚
	 */
	public void add(E value,int level) {
		if(list.contains(value)) {
			return;
		}
		list.add(value);
		upNode = new Node(value,level,fixDouble(value),upNode);
		firstUpNode = upNode;
	}
	
	/**
	 * 从字符串中获取起权重
	 * @param value 字符串中获取起权重
	 * @return 权重
	 * 2014年8月27日
	 * @author 马宝刚
	 */
	public static double fixDouble(Object value) {
		if(value==null) {
			return 0;
		}
		byte[] bytes = null; //拆解成字节
		try {
			bytes = value.toString().getBytes(StandardCharsets.UTF_8);
		}catch(Exception e) {
			bytes = value.toString().getBytes();
		}
		double reDouble = 0; //构建返回值
		for(int i=0;i<bytes.length;i++) {
			reDouble += ((int)bytes[i])*Math.pow(10,(bytes.length-i));
		}
		return reDouble;
	}
	
	/**
	 * 由小到大排列
	 * 马宝刚
	 * 2009-12-2 上午10:44:39
	 */
	public void asc() {
		asc = true;
		upNode = firstUpNode;
		if(upNode==null) {
			return;
		}
		upNode = upNode.getBottomNode();
	}
	
	/**
	 * 由大到小排列
	 * 马宝刚
	 * 2009-12-2 上午10:45:08
	 */
	public void desc() {
		asc = false;
		upNode = firstUpNode;
		if(upNode==null) {
			return;
		}
		upNode = upNode.getTopNode();
	}
	
	/**
	 * 重置排序（准备重新获取值）
	 * 2019年1月3日
	 * @author MBG
	 */
	public void reset() {
		upNode = firstUpNode;
	}
	
	/**
	 * 获取当前值，并且将指针移到下一个值的位置上
	 * 马宝刚
	 * 2009-12-2 上午10:48:08
	 * @return 当前值
	 */
	public E nextValue() {
		if(upNode==null) {
			return null;
		}
		//获取返回值
		E reObj = upNode.value;
		if(asc) {
			upNode = upNode.pNode;
		}else {
			upNode = upNode.cNode;
		}
		return reObj;
	}
	
	/**
	 * 是否存在下一个值
	 * 马宝刚
	 * 2009-12-2 上午10:45:58
	 * @return 是否存在下一个值
	 */
	public boolean hasNext() {
		return upNode != null;
	}
	
	/**
	 * 转换成序列
	 * @return 序列
	 * 2014年8月27日
	 * @author 马宝刚
	 */
	public List<E> toList(){
		//构建返回值
		List<E> reList = new ArrayList<E>();
		while(hasNext()) {
			reList.add(nextValue());
		}
		return reList;
	}
	
	
	/**
	 * 移除指定对象
	 * @param bean 指定对象
	 * @return     被移除的对象
	 * 2019年1月2日
	 * @author MBG
	 */
	public E remove(E bean){
		if(bean==null || !list.contains(bean)) {
			return bean;
		}
		if(firstUpNode.value!=null && firstUpNode.value.equals(bean)) {
			firstUpNode = firstUpNode.cNode;
			firstUpNode.pNode = firstUpNode;
			return bean;
		}
		//递归调用移除指定值
		doRemove(firstUpNode.cNode,bean);
		return bean;
	}
	
	
	/**
	 * 递归移除指定节点对象
	 * @param node   节点
	 * @param bean   节点值对象
	 * @return       是否处理完毕
	 * 2019年1月2日
	 * @author MBG
	 */
	private boolean doRemove(Node node,E bean) {
		if(node.value!=null && node.value.equals(bean)) {
			if(node.cNode==null) {
				//不会走到这步
				return true;
			}
			if(node.equals(node.cNode)) {
				//末级节点
				node.pNode.cNode = node.pNode;
				return true;
			}
			node.pNode = node.cNode;
			return true;
		}
		if(node.cNode==null || node.equals(node.cNode)) {
			//已经是末级节点
			return true;
		}
		return doRemove(node.cNode,bean);
	}
}
